//
//  MemorizeGame.swift
//  Memorize
//
//  Created by YJH on 2025/4/22.
//

import Foundation

struct MemoryGame<CardContent> where CardContent: Equatable {
    private(set) var cards: Array<Card>
    
    init(numberOfPairsOfCards: Int,cardContentFactory: (Int) -> CardContent){
        cards = []
        for pairIndex in 0..<max(2,numberOfPairsOfCards){
            let content: CardContent = cardContentFactory(pairIndex)
            cards.append(Card(id: "\(pairIndex+1)a", content: content))
            cards.append(Card(id: "\(pairIndex+1)b", content: content))

        }
        
    }
    
    var indexOfTheOneAndOnlyFaceUpCard: Int? {
        get{
             cards.indices.filter {index in cards[index].isFaceUp}.only
            
//            return faceUpCardIndices.count == 1 ? faceUpCardIndices.first : nil   扩展
            
//            var faceUpCardIndices = [Int]()
//            for index in cards.indices {
//                if cards[index].isFaceUp{
//                    faceUpCardIndices.append(index)
//                }
//            }
//            if faceUpCardIndices.count == 1 {
//                return faceUpCardIndices.first
//            } else{
//                return nil
//            }
        }
        set{
            cards.indices.forEach { cards[$0].isFaceUp = (newValue == $0)}
//            for index in cards.indices {
//                if index == newValue {
//                    cards[index].isFaceUp = true
//                } else {
//                    cards[index].isFaceUp = false
//                }
//            }
        }
    }
    
    mutating func choose(_ card: Card){
        if let chosenIndex = cards.firstIndex(where: {$0.id == card.id}){
            if !cards[chosenIndex].isFaceUp && !cards[chosenIndex].isMatched{
                if let potentialMatchIndex = indexOfTheOneAndOnlyFaceUpCard{
                    if cards[chosenIndex].content == cards[potentialMatchIndex].content {
                        cards[chosenIndex].isMatched = true
                        cards[potentialMatchIndex].isMatched =  true
                    }
//                    indexOfTheOneAndOnlyFaceUpCard = nil
                } else{
//                    for index in cards.indices {
//                        cards[index].isFaceUp = false
//                    }
                    indexOfTheOneAndOnlyFaceUpCard = chosenIndex
                }
                cards[chosenIndex].isFaceUp = true
            }
        }
    }
    
    
    mutating func shuffle(){
        cards.shuffle()
        print(cards)
    }
    
    struct Card :Equatable,Identifiable, CustomStringConvertible{
        var description: String {
            "\(id): \(content) \(isFaceUp ? "up" : "down") \(isMatched ? "matched" : "")"
        }
        
        var id: String


        var isFaceUp = false
        var isMatched = false
        let content: CardContent
        
    }
}

extension Array {
    var only : Element? {
        return count == 1 ? first : nil
    }
}

